package com.yfk.web.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yfk.web.entity.OAToYHTVO;
import com.yfk.web.service.IYHTService;
import com.yfk.web.util.BIPUtil;
import com.yfk.web.util.HttpClientUtil;
import com.yfk.web.util.ResultDataUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@RestController
@RequestMapping("/OAService")
public class YHTAndOAController {

    Logger logger = LoggerFactory.getLogger(YHTAndOAController.class);

    @Autowired
    public OAToYHTVO oaToYHTVO;

    @Autowired
    public IYHTService yhtService;

    @RequestMapping("/yonyouYHTApproveCount")
    public String getYhtApproveCount(@RequestParam("jobNumber") String userCode) throws Exception {
        String result = "";
        try {
            String accessToken = BIPUtil.getAccessToken(this.getYHTToKenURL(this.oaToYHTVO.baseURL),
                    this.oaToYHTVO.appKey, this.oaToYHTVO.appSecret);
            if (accessToken == null || "".equals(accessToken)) {
                String errorMessage = "获取友合同内部系统token异常";
                throw new Exception(errorMessage);
            }
            Map queryParams = new HashMap();
            queryParams.put("access_token", accessToken);
            queryParams.put("jobNumber", userCode);
            String apiUrl = this.oaToYHTVO.getBaseURL() + this.oaToYHTVO.getGetwayurl() + this.oaToYHTVO.getApproveCount();
            result = HttpClientUtil.doGet(apiUrl, null, queryParams).toString();
        } catch (Exception e) {
            result = ResultDataUtil.error(e.getMessage());
        }
        return result;
    }

    /**
     * 设置请求头
     *
     * @param mapParams
     * @return
     * @throws Exception
     */
    public String setUrlParams(Map<String, Object> mapParams) throws Exception {
        // 是否已经设置了问号
        boolean hasSetQuestionMark = false;
        StringBuffer strParams = new StringBuffer();
        if (mapParams != null) {
            Iterator<String> iterator = mapParams.keySet().iterator();
            String key = "";
            while (iterator.hasNext()) {
                try {
                    key = iterator.next();
                    if (!hasSetQuestionMark) {
                        strParams.append("?").append(key).append("=")
                                .append(mapParams.get(key).toString());
                        // .append(URLEncoder.encode(mapParams.get(key).toString(), "utf-8"));
                        hasSetQuestionMark = true;
                        continue;
                    }
                    strParams.append("&").append(key).append("=")
                            .append(mapParams.get(key).toString());
                } catch (Exception e) {
                    throw new Exception(e.getMessage());
                }
            }
        }
        return strParams.toString();
    }

    @RequestMapping("/yonyouHOPToHT")
    public void OALoginToYHT(@RequestParam("code") String OACode, @RequestParam("from") String from, HttpServletRequest req, HttpServletResponse resp) throws Exception {
        String redirectURL = this.oaToYHTVO.getBaseURL();
        try {
            RestTemplateBuilder builder = new RestTemplateBuilder();
            RestTemplate template = builder.build();
            logger.info("######OA系统进行单点登录操作");
            String oaurl = "";
            if ("in".equals(from)) { // 因为前置机都能访问OA域名
                oaurl = "192.168.102.175:8087";//正式内网
            } else {
                oaurl = this.oaToYHTVO.oaURL;
            }
            String oaTokenUrl = this.getOATokenUrl(oaurl);
            String url = "";
//            if("in".equals(from)){
//                url = "http://" +this.oaToYHTVO.getTbbj()+"/OAService/yonyouHOPToHT";
//            }else{
            url = "http://172.16.100.114:7070/OAService/yonyouHOPToHT";
//            }
            Map<String, Object> requestParam = this.getRequestParam(OACode, url);
            String toKenBody = "";
            ObjectMapper objectMapper = new ObjectMapper();
            String oatoken = objectMapper.writeValueAsString(requestParam);
            try {
                oaTokenUrl = oaTokenUrl + this.setUrlParams(requestParam);
                toKenBody = template.postForObject(oaTokenUrl, oatoken, String.class);
            } catch (Exception e) {
                throw new Exception("#####请求地址:【" + oaTokenUrl + "】,请求参数:【" + oatoken + "】,获取OA系统token异常: [" + e.getMessage() + "]");
            }
//            String toKenBody = HttpClientUtil.doGet(oaTokenUrl, null, requestParam);
            logger.info("######获取OA系统token,请求地址:" + oaTokenUrl + ",请求参数:[" + oatoken + "],接口响应:" + toKenBody);
//        String toKenBody = "123123&11111";
            if (toKenBody == null || "".equals(toKenBody)) {// 获取OA系统Token异常
                String errorMessage = "#####友合同单点登陆获取OA token响应结果【" + toKenBody + "】为空,请OA开发人员处理!";
                throw new Exception(errorMessage);
            } else {
                String token = toKenBody.split("&")[0].replace("access_token=", "");
                requestParam.put("access_token", token);
                String oaprourl = this.getOAProfileURL(this.oaToYHTVO.oaURL);
//                String proFileBody = template.postForObject(oaprourl,requestParam,String.class);
                String proFileBody = HttpClientUtil.doGet(oaprourl, null, requestParam);
                logger.info("######获取OA系统登录人信息,请求地址:" + oaprourl + ",请求参数:[" + requestParam.toString() + "],接口响应:" + proFileBody);
//            String proFileBody = "{'id':'wy'}";
                if (proFileBody == null || "".equals(proFileBody)) {
                    String errorMessage = "友合同获取OA登录人信息异常,接口响应信息:【" + proFileBody +
                            "】,请联系OA开发人员处理!";
                    throw new Exception(errorMessage);
                } else {
                    JSONObject json = JSONObject.parseObject(proFileBody);
                    String oaUeerCode = json.getString("id");
                    logger.info("####准备获取友合同内部token");
                    String accessToken = BIPUtil.getAccessToken(this.getYHTToKenURL(this.oaToYHTVO.baseURL),
                            this.oaToYHTVO.appKey, this.oaToYHTVO.appSecret);
                    if (accessToken == null || "".equals(accessToken)) {
                        String errorMessage = "获取友合同内部系统token异常";
                        throw new Exception(errorMessage);
                    }
//                oaUeerCode = "c3855d10-7f7f-44df-9321-900f9edf4eea";
                    logger.info("####准备获取友合同用户信息:" + oaUeerCode);
                    String yhtUserInfoByCode = this.yhtService.getYHTUserInfoByCode(oaUeerCode, this.oaToYHTVO.getThirdUCId(), accessToken);
                    if (yhtUserInfoByCode == null || "".equals(yhtUserInfoByCode)) {
                        throw new Exception("获取用户信息:【" + oaUeerCode + "】异常!");
                    }
                    JSONObject yhtUserInfo = JSONObject.parseObject(yhtUserInfoByCode);
                    if (200 != yhtUserInfo.getIntValue("code")) {
                        throw new Exception("获取用户信息:【" + oaUeerCode + "】异常:" + yhtUserInfo.toJSONString());
                    }
                    String USER_ID = yhtUserInfo.getJSONArray("data").getJSONObject(0).getString("USER_ID");
                    logger.info("####准备获取友合同临时登录token");
                    String loginResponse = this.yhtService.getThirdLoginCode("YHT", this.oaToYHTVO.baseURL, accessToken, this.oaToYHTVO.getJcrzzx(),
                            USER_ID);
                    if (loginResponse == null || "".equals(loginResponse))
                        throw new Exception("获取友合同集成认证临时登录code异常！");
                    JSONObject jsonResponse = JSON.parseObject(loginResponse);
                    if ("200".equals(jsonResponse.getString("code"))) {
                        JSONObject data = jsonResponse.getJSONObject("data");
                        String code = data.getString("code");// 临时code
                        logger.info("####准备进行单点登录地址");
                        if ("".equals(code) || code == null || !data.getBoolean("isBindYhtUser")) {
                            // 该联邦用户中心尚未在友户通注册，无法使用单点登录服务 需要进入到注册界面
                            redirectURL = this.getloginURL("YHT", code, this.oaToYHTVO.getJcrzzx(), this.oaToYHTVO.getThirdUCId(),
                                    this.oaToYHTVO.getBaseURL(), this.oaToYHTVO.getBaseURL());
                        } else { // 正常进行单点登录,说明不是第一次登陆
                            String logincode = jsonResponse.getJSONObject("data").getString("code");
                            redirectURL = this.yhtService.getSignLoginURL(this.oaToYHTVO.getThirdUCId(), "YHT", this.oaToYHTVO.getBaseURL(),
                                    this.oaToYHTVO.getJcrzzx(),
                                    this.oaToYHTVO.getBaseURL() + "/login", logincode);
                        }
                    } else {
                        throw new Exception(loginResponse);
                    }

                }

            }

        } catch (Exception e) {
            logger.error("####OA系统单点登录友合同异常:【" + e.getMessage() + "】");
            throw new Exception(e.getMessage());
        }

        resp.sendRedirect(redirectURL);

    }

    public String getloginURL(String system, String userCode, String thirdUCId, String qycode, String baseURL,
                              String redirectedURL) throws Exception {
        String loginURL = "";
        if ("YHT".equals(system)) {
            loginURL = String.format("%s/cas/thirdOauth2CodeLogin?thirdUCId=%s&code=%s&service=%s", baseURL, thirdUCId,
                    userCode, encode(redirectedURL, true, qycode));
        } else if ("YFK".equals(system)) {
            loginURL = String.format("%s/cas/thirdOauth2CodeLogin?thirdUCId=%s&code=%s&service=%s", baseURL, thirdUCId,
                    userCode, encode(redirectedURL, true, qycode));
        }
        return loginURL;
    }

    private String encode(String url, boolean isNeedTenantId, String qycode) throws Exception {
        try {
            if (isNeedTenantId) {
                if (StringUtils.contains(url, "?")) {
                    return URLEncoder.encode(url + "&tenantId=" + qycode, StandardCharsets.UTF_8.toString());
                } else {
                    return URLEncoder.encode(url + "?tenantId=" + qycode, StandardCharsets.UTF_8.toString());
                }
            } else {
                return URLEncoder.encode(url, StandardCharsets.UTF_8.toString());
            }
        } catch (Exception e) {
            throw new Exception("url转义异常：" + url);
        }
    }

    /**
     * 获取当前当前登录人的信息URL
     *
     * @param ipAndPort
     * @return
     * @throws Exception
     */
    private String getOAProfileURL(String ipAndPort) throws Exception {
        String OAURL = String.format("https://%s/cas-server/oauth2.0/profile", ipAndPort);
        return OAURL;
    }

    /**
     * 获取友合同token地址
     *
     * @param ipAndPort
     * @return
     * @throws Exception
     */
    private String getYHTToKenURL(String ipAndPort) throws Exception {
        return ipAndPort + "/iuap-api-auth/open-auth/selfAppAuth/getAccessToken";
    }

    /**
     * 获取请求oa参数
     *
     * @param userCode OA系统临时code
     * @param url      OA系统回调地址
     * @return
     * @throws Exception
     */
    private Map<String, Object> getRequestParam(String userCode, String url) throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("code", userCode);
        map.put("redirect_uri", url);
        map.put("client_id", this.oaToYHTVO.oaClientId);
        map.put("client_secret", this.oaToYHTVO.oaClientSecret);
        return map;
    }

    /**
     * 获取OAtoken地址
     *
     * @param ipAndPort OA系统ip+端口
     * @return
     * @throws Exception
     */
    private String getOATokenUrl(String ipAndPort) throws Exception {
        String OAURL = String.format("https://%s/cas-server/oauth2.0/accessToken", ipAndPort);
        return OAURL;
    }

}
